﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Download.Core;

namespace AutoUpdater
{
    public class ProgressWatcherEventArgs : System.EventArgs
    {
        public string FileName { get; private set; }
        public string TotalRate { get; private set; }
        public string Rate { get; private set; }
        public int Progress { get; private set; }
        public int TotalProgress { get; private set; }

        public ProgressWatcherEventArgs(string fileName, string totalRate,
            string rate, int progress, int totalProgress) {
            this.FileName = fileName;
            this.TotalRate = totalRate;
            this.Rate = rate;
            this.Progress = progress;
            this.TotalProgress = totalProgress;
        }
    }

    public class ProgressWatcher
    {
        #region 字段
        private DownloadManager downloadManger;
        private IndexSwither indexer;
        private int totalTaskCount = 0;
        private int taskDoneCount = 0;
        private object mutex = new object();
        private bool isCompleted;
        #endregion

        #region 属性
        /// <summary>
        /// 完成总数
        /// </summary>
        public int TaskDoneCount {
            get {
                lock (mutex) {
                    return this.taskDoneCount;
                }
            }
            set {
                lock (mutex) {
                    this.taskDoneCount = value;
                }
            }
        }
        /// <summary>
        /// 是否全部完成
        /// </summary>
        public Boolean IsCompleted {
            get {
                lock (mutex) {
                    return this.isCompleted;
                }
            }
            set {
                lock (mutex) {
                    this.isCompleted = value;
                }
            }
        }
        #endregion

        #region 事件
        /// <summary>
        /// 更新事件
        /// </summary>
        public event EventHandler<ProgressWatcherEventArgs> Updating;
        /// <summary>
        /// 完成事件
        /// </summary>
        public event EventHandler Completed;

        public event EventHandler Initialized;

        #endregion

        #region 构造器
        public ProgressWatcher(DownloadManager downloadManger) {

            this.downloadManger = downloadManger;
            this.totalTaskCount = downloadManger.Downloads.Count;
            this.isCompleted = false;
            this.indexer = new IndexSwither(totalTaskCount - 1);

            RegsiterEvents();
        }


        #endregion

        #region 方法
        /// <summary>
        /// 初始化模拟定时器
        /// </summary>
        public void Start() {
            ThreadPool.QueueUserWorkItem(new WaitCallback(TimerTick));
            Thread.Sleep(1000);
            OnInitialized();

        }
        /// <summary>
        /// 注册事件
        /// </summary>
        private void RegsiterEvents() {
            foreach (var item in this.downloadManger.Downloads) {
                item.StateChanged += OnStateChanged;
            }
        }

        private void OnInitialized() {
            if (this.Initialized != null) {
                this.Initialized(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 状态改变事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnStateChanged(object sender, EventArgs e) {
            var downloader = sender as Downloader;
            if (downloader.State == DownloaderState.Ended) {
                TaskDoneCount++;
            }
            var taskDoneCount = this.TaskDoneCount;
            if (taskDoneCount == totalTaskCount) {
                OnCompleted();
            }
        }

        /// <summary>
        /// 触发完成事件
        /// </summary>
        private void OnCompleted() {
            IsCompleted = true;
            if (this.Completed != null) {
                Completed(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// 触发更新事件
        /// </summary>
        /// <param name="e"></param>
        protected void OnUpdating(ProgressWatcherEventArgs e) {
            if (this.Updating != null) {
                this.Updating(this, e);
            }
        }

        /// <summary>
        /// 模拟定时器
        /// </summary>
        /// <param name="o"></param>
        private void TimerTick(object o) {
            while (!IsCompleted) {
                var index = indexer.Next;
                var downloader = this.downloadManger.Downloads[indexer.Next];

                if (downloader.State == DownloaderState.Working) {
                    var totalProgress = GetTotalProgress();
                    var currentFile = GetFileName(downloader.ResourceLocation.URL);
                    var totalRate = GetRate(downloadManger.TotalDownloadRate);
                    var rate = GetRate(downloader.Rate);
                    this.OnUpdating(new ProgressWatcherEventArgs(currentFile,
                        totalRate, rate, (int)downloader.Progress, (int)totalProgress));
                }

                Thread.Sleep(1000);
            }

        }

        /// <summary>
        /// 获取文件名字
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private string GetFileName(string url) {
            var remoteUri = new Uri(url);
            string filename = remoteUri.Segments[remoteUri.Segments.Length - 1];

            return Uri.UnescapeDataString(filename);
        }

        /// <summary>
        /// 获取速率
        /// </summary>
        /// <param name="rate"></param>
        /// <returns></returns>
        private string GetRate(double rate) {

            if (rate > 1024 * 1024) {
                return string.Format("{0} MB/s", (int)(rate / 1024 * 1024));
            } else if (rate > 1024) {
                return string.Format("{0} KB/s", (int)(rate / 1024));
            } else if (rate > 0) {
                return string.Format("{0} B/s", (int)rate);
            } else {
                return "0 B/s";
            }
        }
        /// <summary>
        /// 获取总进度
        /// </summary>
        /// <returns></returns>
        private double GetTotalProgress() {
            var per = 100.0 / indexer.Count;
            double totalProgress = 0;
            foreach (var item in this.downloadManger.Downloads) {
                totalProgress += (item.Progress / 100.0) * per;
            }
            if (totalProgress > 100.0) {
                totalProgress = 100.0;
            }
            return totalProgress;
        }
        #endregion

        #region 内部类
        class IndexSwither
        {
            private int current;
            private int maxIndex;
            public IndexSwither(int maxIndex) {
                this.maxIndex = maxIndex;
                this.current = 0;
            }

            public int Next {
                get {
                    this.current = this.current + 1;
                    if (this.current > maxIndex) {
                        this.current = 0;
                    }
                    return this.current;
                }
            }

            public int Count {
                get { return maxIndex + 1; }
            }
        }
        #endregion
    }
}
